home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / sbin / runscript.sh < prev    next >
Linux/UNIX/POSIX Shell Script  |  2006-04-25  |  13KB  |  505 lines

  1. #!/bin/bash
  2. # Copyright 1999-2005 Gentoo Foundation
  3. # Distributed under the terms of the GNU General Public License v2
  4. # $Header$
  5.  
  6. # Common functions
  7. [[ ${RC_GOT_FUNCTIONS} != "yes" ]] && source /sbin/functions.sh
  8. # Functions to handle dependencies and services
  9. [[ ${RC_GOT_SERVICES} != "yes" ]] && source "${svclib}/sh/rc-services.sh"
  10. # Functions to control daemons
  11. [[ ${RC_GOT_DAEMON} != "yes" ]] && source "${svclib}/sh/rc-daemon.sh"
  12.  
  13. # User must be root to run most script stuff (except status)
  14. if [[ ${EUID} != 0 ]] && ! [[ $2 == "status" && $# -eq 2 ]] ; then
  15.     eerror "$0: must be root to run init scripts"
  16.     exit 1
  17. fi
  18.  
  19. # Stop init scripts from working until sysinit completes
  20. if [[ -e /dev/.rcsysinit ]] ; then
  21.     eerror "ERROR:  cannot run ${myservice} until sysinit completes"
  22.     exit 1
  23. fi
  24.         
  25. # State variables
  26. svcpause="no"
  27. svcrestart="no"
  28.  
  29. myscript="$1"
  30. if [[ -L $1 ]] && [[ ! -L /etc/init.d/${1##*/} ]] ; then
  31.     myservice=$(readlink "$1")
  32. else
  33.     myservice=$1
  34. fi
  35.  
  36. myservice=${myservice##*/}
  37. export SVCNAME=${myservice}
  38. mylevel=$(<"${svcdir}/softlevel")
  39.  
  40.  
  41. # Set $IFACE to the name of the network interface if it is a 'net.*' script
  42. if [[ ${myservice%%.*} == "net" ]] && [[ ${myservice##*.} != ${myservice} ]] ; then
  43.     IFACE=${myservice##*.}
  44.     NETSERVICE="yes"
  45. else
  46.     IFACE=
  47.     NETSERVICE=
  48. fi
  49.  
  50. # We need to stop hotplug from launching net scripts until the boot level
  51. # has completed
  52. if [[ ${NETSERVICE} == "yes" && ${IFACE} != "lo" ]] ; then
  53.     if [[ -z ${mylevel} || ${mylevel} == ${BOOTLEVEL} ]] ; then
  54.         eerror "${myservice}: cannot start until the runlevel ${BOOTLEVEL} has completed"
  55.         exit 1
  56.     fi
  57. fi
  58.  
  59. # Source configuration files.
  60. # (1) Source /etc/conf.d/${myservice} to get initscript-specific
  61. #     configuration (if it exists).
  62. # (2) Source /etc/conf.d/net if it is a net.* service
  63. # (3) Source /etc/rc.conf to pick up potentially overriding
  64. #     configuration, if the system administrator chose to put it
  65. #     there (if it exists).
  66.  
  67. [[ -e $(add_suffix /etc/conf.d/${myservice}) ]] && source "$(add_suffix /etc/conf.d/${myservice})"
  68. [[ -e $(add_suffix /etc/conf.d/net) ]]          && \
  69. [[ ${NETSERVICE} == "yes" ]]                    && source "$(add_suffix /etc/conf.d/net)"
  70. [[ -e $(add_suffix /etc/rc.conf) ]]             && source "$(add_suffix /etc/rc.conf)"
  71.  
  72.  
  73. usage() {
  74.     local IFS="|"
  75.     myline="Usage: ${myservice} { $* "
  76.     echo
  77.     eerror "${myline}}"
  78.     eerror "       ${myservice} without arguments for full help"
  79. }
  80.  
  81. stop() {
  82.     # Return success so the symlink gets removed
  83.     return 0
  84. }
  85.  
  86. start() {
  87.     eerror "ERROR:  \"${myservice}\" does not have a start function."
  88.     # Return failure so the symlink doesn't get created
  89.     return 1
  90. }
  91.  
  92. restart() {
  93.     svc_restart || return $?
  94. }
  95.  
  96. status() {
  97.     # Dummy function
  98.     return 0
  99. }
  100.             
  101. svc_stop() {
  102.     local x=
  103.     local mydep=
  104.     local mydeps=
  105.     local retval=0
  106.     local ordservice=
  107.  
  108.     if ! service_started "${myservice}" ; then
  109.         if [[ ${RC_QUIET_STDOUT} != "yes" ]] ; then
  110.             eerror "ERROR:  \"${myservice}\" has not yet been started."
  111.         fi
  112.         return 0
  113.     fi
  114.  
  115.     # Do not try to stop if it had already failed to do so on runlevel change
  116.     if is_runlevel_stop && service_failed "${myservice}" ; then
  117.         exit 1
  118.     fi
  119.  
  120.     # Remove symlink to prevent recursion
  121.     mark_service_stopped "${myservice}"
  122.  
  123.     if in_runlevel "${myservice}" "${BOOTLEVEL}" && \
  124.        [[ ${SOFTLEVEL} != "reboot" && ${SOFTLEVEL} != "shutdown" && ${SOFTLEVEL} != "single" ]]
  125.     then
  126.         ewarn "WARNING:  you are stopping a boot service."
  127.     fi
  128.  
  129.     if [[ ${svcpause} != "yes" && ${RC_NODEPS} != "yes" ]] ; then
  130.         if [[ ${NETSERVICE} == "yes" ]] ; then
  131.             # A net.* service
  132.             if in_runlevel "${myservice}" "${BOOTLEVEL}" || \
  133.                in_runlevel "${myservice}" "${mylevel}"
  134.             then
  135.                 # Only worry about net.* services if this is the last one running,
  136.                 # or if RC_NET_STRICT_CHECKING is set ...
  137.                 if ! is_net_up ; then
  138.                     mydeps="net"
  139.                 fi
  140.             fi
  141.             
  142.             mydeps="${mydeps} ${myservice}"
  143.         else
  144.             mydeps="${myservice}"
  145.         fi
  146.     fi
  147.  
  148.     for mydep in ${mydeps} ; do
  149.         # If some service 'need' $mydep, stop it first; or if it is a runlevel change,
  150.         # first stop all services that is started 'after' $mydep.
  151.         if needsme "${mydep}" >/dev/null || \
  152.            (is_runlevel_stop && ibefore "${mydep}" >/dev/null)
  153.         then
  154.             local servicelist="$(needsme "${mydep}")"
  155.  
  156.             # On runlevel change, stop all services "after $mydep" first ...
  157.             is_runlevel_stop && servicelist="${servicelist} $(ibefore "${mydep}")"
  158.  
  159.             for x in ${servicelist} ; do
  160.                 # Make sure we have a relevant rc-script ...
  161.                 if [[ ${x} != "net" && ! -f /etc/init.d/${x} ]] ; then
  162.                     continue
  163.                 fi
  164.  
  165.                 # Service not currently running, continue
  166.                 service_started "${x}" || continue
  167.  
  168.                 if ibefore -t "${mydep}" "${x}" >/dev/null && \
  169.                    [[ -L ${svcdir}/softscripts.new/${x} ]]
  170.                 then
  171.                     # Service do not 'need' $mydep, and is still present in
  172.                     # new runlevel ...
  173.                     continue
  174.                 fi
  175.  
  176.                 stop_service "${x}"
  177.  
  178.                 if [[ $? -ne 0 ]] ; then
  179.                     # If we are halting the system, try and get it down as
  180.                     # clean as possible, else do not stop our service if
  181.                     # a dependent service did not stop.
  182.                     if needsme -t "${mydep}" "${x}" >/dev/null && \
  183.                        [[ ${SOFTLEVEL} != "reboot" && ${SOFTLEVEL} != "shutdown" ]]
  184.                     then
  185.                         retval=1
  186.                     fi
  187.  
  188.                     break
  189.                 fi
  190.             done
  191.         fi
  192.     done
  193.  
  194.     if [[ ${retval} -ne 0 ]] ; then
  195.         eerror "ERROR:  problems stopping dependent services."
  196.         eerror "        \"${myservice}\" is still up."
  197.     else
  198.         # Now that deps are stopped, stop our service
  199.         stop
  200.         retval="$?"
  201.     fi
  202.     
  203.     if [[ ${retval} -ne 0 ]] ; then
  204.         # Did we fail to stop? create symlink to stop multible attempts at
  205.         # runlevel change.  Note this is only used at runlevel change ...
  206.         if is_runlevel_stop ; then
  207.             mark_service_failed "${myservice}"
  208.         fi
  209.         
  210.         # If we are halting the system, do it as cleanly as possible
  211.         if [[ ${SOFTLEVEL} != "reboot" && ${SOFTLEVEL} != "shutdown" ]] ; then
  212.             mark_service_started "${myservice}"
  213.         fi
  214.     fi
  215.  
  216.     return "${retval}"
  217. }
  218.  
  219. svc_start() {
  220.     local retval=0
  221.     local startfail="no"
  222.     local x=
  223.     local y=
  224.     local myserv=
  225.     local ordservice=
  226.  
  227.     if ! service_started "${myservice}" ; then
  228.         # Do not try to start if i have done so already on runlevel change
  229.         if is_runlevel_start && service_failed "${myservice}" ; then
  230.             exit 1
  231.         fi
  232.     
  233.         # Link first to prevent possible recursion
  234.         mark_service_started "${myservice}"
  235.  
  236.         # On rc change, start all services "before $myservice" first
  237.         if [[ ${RC_NODEPS} != "yes" ]] ; then
  238.             if is_runlevel_start ; then
  239.                 startupservices="$(ineed "${myservice}") \
  240.                     $(valid_iuse "${myservice}") \
  241.                     $(valid_iafter "${myservice}")"
  242.             else
  243.                 startupservices="$(ineed "${myservice}") \
  244.                     $(valid_iuse "${myservice}")"
  245.             fi
  246.         fi
  247.  
  248.         # Start dependencies, if any
  249.         for x in ${startupservices} ; do
  250.             if [[ ${x} == "net" && ${NETSERVICE} != "yes" ]] && ! is_net_up ; then
  251.                 local netservices="$(dolisting "/etc/runlevels/${BOOTLEVEL}/net.*") \
  252.                     $(dolisting "/etc/runlevels/${mylevel}/net.*")"
  253.  
  254.                 for y in ${netservices} ; do
  255.                     mynetservice="${y##*/}"
  256.  
  257.                     if ! service_started "${mynetservice}" ; then
  258.                         start_service "${mynetservice}"
  259.  
  260.                         # A 'need' dependency is critical for startup
  261.                         if [[ $? -ne 0 ]] && ineed -t "${myservice}" "${x}" >/dev/null ; then
  262.                             # Only worry about a net.* service if we do not have one
  263.                             # up and running already, or if RC_NET_STRICT_CHECKING
  264.                             # is set ....
  265.                             if ! is_net_up ; then
  266.                                 startfail="yes"
  267.                             fi
  268.                         fi
  269.                     fi
  270.                 done
  271.  
  272.             elif [[ ${x} != "net" ]] ; then
  273.                 if ! service_started "${x}" ; then
  274.                     start_service "${x}"
  275.  
  276.                     # A 'need' dependacy is critical for startup
  277.                     if [[ $? -ne 0 ]] && ineed -t "${myservice}" "${x}" >/dev/null ; then
  278.                         startfail="yes"
  279.                     fi
  280.                 fi
  281.             fi
  282.         done
  283.  
  284.         if [[ ${startfail} == "yes" ]] ; then
  285.             eerror "ERROR:  Problem starting needed services."
  286.             eerror "        \"${myservice}\" was not started."
  287.             retval=1
  288.         fi
  289.  
  290.         # Start service
  291.         if [[ ${retval} -eq 0 ]] && broken "${myservice}" ; then
  292.             eerror "ERROR:  Some services needed are missing.  Run"
  293.             eerror "        './${myservice} broken' for a list of those"
  294.             eerror "        services.  \"${myservice}\" was not started."
  295.             retval=1
  296.         elif [[ ${retval} -eq 0 ]] && ! broken "${myservice}" ; then
  297.             (
  298.             exit() {
  299.                 eerror "DO NOT USE EXIT IN INIT.D SCRIPTS"
  300.                 eerror "This IS a bug, please fix your broken init.d"
  301.                 unset -f exit
  302.                 exit $@
  303.             }
  304.             start
  305.             )
  306.             retval="$?"
  307.         fi
  308.  
  309.         if [[ ${retval} -ne 0 ]] && is_runlevel_start ; then
  310.             mark_service_failed "${myservice}"
  311.         fi
  312.  
  313.         # Remove link if service didn't start; but only if we're not booting
  314.         # if we're booting, we need to continue and do our best to get the
  315.         # system up.
  316.         if [[ ${retval} -ne 0 && ${SOFTLEVEL} != ${BOOTLEVEL} ]] ; then
  317.             mark_service_stopped "${myservice}"
  318.         fi
  319.  
  320.         return "${retval}"
  321.     else
  322.         if [[ ${RC_QUIET_STDOUT} != "yes" ]] ; then
  323.             ewarn "WARNING:  \"${myservice}\" has already been started."
  324.         fi
  325.  
  326.         return 0
  327.     fi
  328. }
  329.  
  330. svc_restart() {
  331.     if service_started "${myservice}" ; then
  332.         svc_stop || return "$?"
  333.         sleep 1
  334.     fi
  335.  
  336.     svc_start || return "$?"
  337. }
  338.  
  339. svc_status() {
  340.     # The basic idea here is to have some sort of consistent
  341.     # output in the status() function which scripts can use
  342.     # as an generic means to detect status.  Any other output
  343.     # should thus be formatted in the custom status() function
  344.     # to work with the printed " * status:  foo".
  345.     local efunc="" state=""
  346.  
  347.     if service_started "${myservice}" ; then
  348.         efunc="einfo"
  349.         state="started"
  350.     else
  351.         efunc="eerror"
  352.         state="stopped"
  353.     fi
  354.     [[ ${RC_QUIET_STDOUT} != "yes" ]] \
  355.         && ${efunc} "status:  ${state}"
  356.  
  357.     status
  358.     [[ ${efunc} != "eerror" ]]
  359. }
  360.  
  361. rcscript_errors=$(bash -n "${myscript}" 2>&1) || {
  362.     [[ -n ${rcscript_errors} ]] && echo "${rcscript_errors}" >&2
  363.     eerror "ERROR:  \"${myscript}\" has syntax errors in it; not executing..."
  364.     exit 1
  365. }
  366.  
  367. # set *after* wrap_rcscript, else we get duplicates.
  368. opts=""
  369.  
  370. source "${myscript}"
  371.  
  372. # make sure whe have valid $opts
  373. opts="start stop restart pause zap ${opts}"
  374.  
  375. svc_homegrown() {
  376.     local x arg=$1
  377.     shift
  378.  
  379.     # Walk through the list of available options, looking for the
  380.     # requested one.
  381.     for x in ${opts} ; do
  382.         if [[ ${x} == "${arg}" ]] ; then
  383.             if typeset -F "${x}" &>/dev/null ; then
  384.                 # Run the homegrown function
  385.                 "${x}"
  386.  
  387.                 return $?
  388.             fi
  389.         fi
  390.     done
  391.     x=""
  392.  
  393.     # If we're here, then the function wasn't in $opts.
  394.     [[ -n $* ]] && x="/ $* "
  395.     eerror "ERROR: wrong args ( "${arg}" ${x})"
  396.     # Do not quote this either ...
  397.     usage ${opts}
  398.     exit 1
  399. }
  400.  
  401. shift
  402. if [[ $# -lt 1 ]] ; then
  403.     eerror "ERROR: not enough args."
  404.     usage ${opts}
  405.     exit 1
  406. fi
  407. for arg in $* ; do
  408.     case "${arg}" in
  409.     --quiet)
  410.         RC_QUIET_STDOUT="yes"
  411.         ;;
  412. # We check this in functions.sh ...
  413. #    --nocolor)
  414. #        RC_NOCOLOR="yes"
  415. #        ;;
  416.     --verbose)
  417.         RC_VERBOSE="yes"
  418.         ;;
  419.     --nodeps)
  420.         RC_NODEPS="yes"
  421.     esac
  422. done
  423. for arg in $* ; do
  424.     case "${arg}" in
  425.     stop)
  426.         svc_stop
  427.         ;;
  428.     start)
  429.         svc_start
  430.         ;;
  431.     needsme|ineed|usesme|iuse|broken)
  432.         list_depend_trace "${arg}"
  433.         ;;
  434.     status)
  435.         svc_status
  436.         ;;
  437.     zap)
  438.         if service_started "${myservice}" ; then
  439.             einfo "Manually resetting ${myservice} to stopped state."
  440.             mark_service_stopped "${myservice}"
  441.         fi
  442.         ;;
  443.     restart)
  444.         svcrestart="yes"
  445.  
  446.         # Create a snapshot of started services
  447.         rm -rf "${svcdir}/snapshot/$$"
  448.         mkdir -p "${svcdir}/snapshot/$$"
  449.         cp -a "${svcdir}"/started/* "${svcdir}/snapshot/$$/"
  450.  
  451.         # Simple way to try and detect if the service use svc_{start,stop}
  452.         # to restart if it have a custom restart() funtion.
  453.         if [[ -n $(egrep '^[[:space:]]*restart[[:space:]]*()' "/etc/init.d/${myservice}") ]] ; then
  454.             if [[ -z $(egrep 'svc_stop' "/etc/init.d/${myservice}") || \
  455.                   -z $(egrep 'svc_start' "/etc/init.d/${myservice}") ]]
  456.             then
  457.                 echo
  458.                 ewarn "Please use 'svc_stop; svc_start' and not 'stop; start' to"
  459.                 ewarn "restart the service in its custom 'restart()' function."
  460.                 ewarn "Run ${myservice} without arguments for more info."
  461.                 echo
  462.                 svc_restart
  463.             else
  464.                 restart
  465.             fi
  466.         else
  467.             restart
  468.         fi
  469.  
  470.         # Restart dependencies as well
  471.         if service_started "${myservice}" ; then
  472.             for x in $(dolisting "${svcdir}/snapshot/$$/") ; do
  473.                 if ! service_started "${x##*/}" ; then
  474. #                    schedule_service_startup "${x##*/}"
  475.                     start_service "${x##*/}"
  476.                 fi
  477.             done
  478.         fi
  479.  
  480.         # Wait for any services that may still be running ...
  481. #        [[ ${RC_PARALLEL_STARTUP} == "yes" ]] && wait
  482.  
  483.         rm -rf "${svcdir}/snapshot/$$"
  484.         svcrestart="no"
  485.         ;;
  486.     pause)
  487.         svcpause="yes"
  488.         svc_stop
  489.         svcpause="no"
  490.         ;;
  491.     --quiet|--nocolor|--nodeps)
  492.         ;;
  493.     help)
  494.         exec "${svclib}"/sh/rc-help.sh "${myscript}" help
  495.         ;;
  496.     *)
  497.         # Allow for homegrown functions
  498.         svc_homegrown ${arg}
  499.         ;;
  500.     esac
  501. done
  502.  
  503.  
  504. # vim:ts=4
  505.